package com.caregiver.watch.business.data.parser;

import com.caregiver.watch.business.care.service.FenceService;
import com.caregiver.watch.business.data.model.po.HealthDeviceLocation;
import com.caregiver.watch.business.data.protobuf.RealtimeData;
import com.caregiver.watch.business.data.service.HealthDataService;
import com.caregiver.watch.business.user.service.UserDeviceService;
import com.caregiver.watch.common.utils.collection.ListUtils;
import com.caregiver.watch.common.utils.number.BigDecimalUtils;
import com.caregiver.watch.common.utils.time.DateUtils;
import com.google.protobuf.InvalidProtocolBufferException;
import com.caregiver.watch.business.data.protobuf.Om0Command;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.caregiver.watch.business.data.enums.PayloadOptTypeProtoEnum.OM_0_REPORT;

/**
 * 0x0A协议解析
 */
@AllArgsConstructor
@Component
@Slf4j
public class OldManDataParser implements IDataParser {


    private final UserDeviceService userDeviceService;
    private final HealthDataService healthDataService;
    private final FenceService fenceService;

    @Override
    public Integer getOpt() {
        return OM_0_REPORT.getOpt();
    }

    @Override
    public void dataParse(Long userId, String deviceId, byte[] payload) {
        Om0Command.OM0Report report;
        try {
            report = Om0Command.OM0Report.parseFrom(payload);
        } catch (InvalidProtocolBufferException ex) {
            log.error("parse om0 report error", ex);
            return;
        }
        int seconds = report.getDateTime().getDateTime().getSeconds();
        LocalDateTime dataTime = DateUtils.convert2LocalDateTime(seconds);
        RealtimeData.RtHealth health = report.getHealth();
        float distance = health.getDistance() * 0.1F;
        float calorie = health.getCalorie() * 0.1F;
        log.info("{} steps:{}, distance:{}, calorie:{}", dataTime, health.getSteps(), distance, calorie);
        // 插入基础健康数据
        healthDataService.insertHealthData(health, deviceId, userId, dataTime);
        RealtimeData.RtBattery battery = report.getBattery();
        // 跟新设备电量和信号
        userDeviceService.updateBatteryAndRssi(userId, deviceId, battery.getLevel(), report.getRssi());
        log.info("{} battery:{}, rssi:{}", dataTime, report.getBattery().getLevel(), report.getRssi());
        // 定位信息 设备上传的位置数据采用的是WGS_84坐标系，而非GCJ_02坐标系。开发者需注意坐标转换，以确保地图显示正确
        parseGnssData(userId, deviceId, report);
        // 解析 设备 配置
        parseOldManCmd(report.getReportOM0());
    }

    /**
     * 0x0A协议解析中的定位信息
     */
    private void parseGnssData(Long userId,
                               String deviceId,
                               Om0Command.OM0Report report) {
        // 插入GPS数据
        List<Om0Command.OM0TrackData> gnssList = report.getTrackDataList();
        log.info("parse gnss data:{}", gnssList);
        if (CollectionUtils.isEmpty(gnssList)) {
            return;
        }
        List<HealthDeviceLocation> deviceLocations = ListUtils.map(gnssList, gnss -> {
            LocalDateTime gnssDate = DateUtils.convert2LocalDateTime(gnss.getTime().getDateTime().getSeconds());
            RealtimeData.RtGNSS rtGNSS = gnss.getGnss();
            log.info("time:{}, lon:{}, lat:{}, loc_type:{}",
                    gnssDate, gnss.getGnss().getLongitude(),
                    gnss.getGnss().getLatitude(),
                    gnss.getGpsType().ordinal());
            HealthDeviceLocation po = new HealthDeviceLocation();
            po.setUserId(userId);
            po.setDeviceUuid(deviceId);
            po.setTrackDataTime(gnssDate);
            // 插入GPS数据
            po.setLongitude(BigDecimalUtils.valueOf(rtGNSS.getLongitude()));
            po.setLatitude(BigDecimalUtils.valueOf(rtGNSS.getLatitude()));
            po.setGpsType(gnss.getGpsType().ordinal());
            po.setCreatedAt(gnssDate);
            return po;
        });
        if(CollectionUtils.isEmpty(deviceLocations)) {
            return;
        }
        healthDataService.insertGnssData(deviceLocations);
        // 触发告警

    }

    /**
     * 解析设备配置
     * 电源模式配置 - 控制设备的功耗管理
     * 数据上传间隔设置 - 定义设备发送数据的时间周期
     * 自动定位配置 - 管理设备的自动定位功能
     * @param omCmd
     */
    void parseOldManCmd(Om0Command.OM0Command omCmd) {
        if (Objects.isNull(omCmd)) {
            return;
        }
        Om0Command.OM0TrackConf trackConf = omCmd.getTrackConf();
        Om0Command.Mc30Powermode powerMode = trackConf.getMc30PowerMode();
        log.info("power mode: {}", powerMode.ordinal());

        boolean autoRun = trackConf.getAutoRun();
        int interval = trackConf.getInterval();
        log.info("data auto upload:{},interval:{}", autoRun ? "open" : "close", interval);
        boolean autoCheck = trackConf.getGpsAutoCheck();
        int gpsInterval = trackConf.getGpsIntervalTime();
        log.info("data auto locate:{},locate interval:{}", autoCheck ? "open" : "close", gpsInterval);
    }
}
